package com.bailiny.zk.demo1;

import org.apache.curator.RetryPolicy;
import org.apache.curator.framework.CuratorFramework;
import org.apache.curator.framework.CuratorFrameworkFactory;
import org.apache.curator.framework.recipes.cache.ChildData;
import org.apache.curator.framework.recipes.cache.TreeCache;
import org.apache.curator.framework.recipes.cache.TreeCacheEvent;
import org.apache.curator.framework.recipes.cache.TreeCacheListener;
import org.apache.curator.retry.ExponentialBackoffRetry;
import org.apache.zookeeper.CreateMode;
import org.testng.annotations.Test;

public class ZkStudy {
    // 连接字符串,这里可以写任意一台服务器地址都可以
    private String connectString = "192.168.52.100:2181,192.168.52.100:2181,192.168.52.100:2181";
    // 重试机制
    private RetryPolicy retryPolicy = new ExponentialBackoffRetry(3000, 3);
    // 获取CuratorFramework对象，就是操作zk的客户端连接对象
    private CuratorFramework client = CuratorFrameworkFactory.newClient(connectString, retryPolicy);

    @Test
    public void createNode() throws Exception {
        // 创建连接
        client.start();
        // 创建永久节点
        client.create().creatingParentsIfNeeded().withMode(CreateMode.PERSISTENT).forPath("/createNode01", "hello world".getBytes());
        client.close();
    }

    @Test
    public void createTempNode() throws Exception {
        // 创建连接
        client.start();
        // 创建临时节点
        client.create().creatingParentsIfNeeded().withMode(CreateMode.EPHEMERAL).forPath("/myTempNode01", "tempNode".getBytes());
        Thread.sleep(10000);
        client.close();
    }

    /**
     * 修改节点数据
     */
    @Test
    public void updateNodeData() throws Exception {
        client.start();
        client.setData().forPath("/createNode01", "update data 20190907".getBytes());
        client.close();
    }

    /**
     * 节点数据查询
     */
    @Test
    public void getDatas() throws Exception {
        client.start();
        byte[] bytes = client.getData().forPath("/createNode01");
        System.out.println(new String(bytes));
        client.close();
    }

    /**
     * zk的watch机制，zk监听只能监听一次，但是这里api已经封装好了不会只监听一次，会一直存在
     */
    @Test
    public void watchNode() throws Exception {
        client.start();
        TreeCache cache = new TreeCache(client, "/createNode01");

        cache.getListenable().addListener(new TreeCacheListener() {
            /**
             * 通过new TreeCacheListener 创建一个内部类，覆写childEvent方法
             * @param curatorFramework 操作zk的客户端
             * @param treeCacheEvent 事件通知类型 封装了节点的修改，删除，新增等一系列的操作
             * @throws Exception
             */
            @Override
            public void childEvent(CuratorFramework curatorFramework, TreeCacheEvent treeCacheEvent) throws Exception {
                ChildData data = treeCacheEvent.getData();
                if (data != null) {
                    // 表示这个节点的数据有变化了

                    // 节点变化类型
                    TreeCacheEvent.Type type = treeCacheEvent.getType();
                    switch (type) {
                        case NODE_ADDED:
                            // 节点新增事件
                            System.out.println("我监听到了节点新增事件");
                            break;
                        case NODE_UPDATED:
                            // 节点的修改事件
                            System.out.println("我监听到了节点的修改事件");
                            break;
                        case INITIALIZED:
                            // 节点的初始化事件
                            System.out.println("我监听到了节点的初始化事件");
                            break;
                        case NODE_REMOVED:
                            // 节点移除事件
                            System.out.println("我监听到了节点移除事件");
                            break;
                        // .......
                        default:
                            break;
                    }

                }
            }
        });
        // 开始监听
        cache.start();
        // 一直监听
        Thread.sleep(600000000);
    }
}
